import re

from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action
from django.contrib.auth.hashers import check_password, make_password

from apps.system.filter.user import UserFilter
from apps.system.models import User, Role, PASSWORD_MIN_LEN, PASSWORD_MAX_LEN, USERNAME_MIN_LEN, USERNAME_MAX_LEN, \
    Permission
from apps.system.serializers.user import UserSerializer
from conf.config import IMAGE_DOMAIN


class UserView(ModelViewSet):
    # queryset = User.objects.all()
    queryset = User.objects.filter(is_delete=False)
    serializer_class = UserSerializer
    # 自定义搜索
    filterset_class = UserFilter

    def create(self, request, *args, **kwargs):

        username = request.data.get('username')
        password = str(request.data.get('password'))
        repassword = str(request.data.get('repassword'))
        email = request.data.get('email')
        mobile = request.data.get('mobile')
        avatar = request.data.get('avatar')
        role = request.data.get('role')

        if not username:
            return Response({'msg': '请输入用户名'}, status=status.HTTP_400_BAD_REQUEST)
        elif len(username) < USERNAME_MIN_LEN:
            return Response({'msg': '用户名长度不能小于5位'}, status=status.HTTP_400_BAD_REQUEST)
        elif len(username) > USERNAME_MAX_LEN:
            return Response({'msg': '用户名长度不能大于20位'}, status=status.HTTP_400_BAD_REQUEST)
        elif not request.data.get('password'):
            return Response({'msg': '请输入密码'}, status=status.HTTP_400_BAD_REQUEST)
        elif not request.data.get('repassword'):
            return Response({'msg': '请输入确认密码'}, status=status.HTTP_400_BAD_REQUEST)
        elif len(password) < PASSWORD_MIN_LEN:
            return Response({'msg': '密码长度不能小于6位'}, status=status.HTTP_400_BAD_REQUEST)
        elif len(password) > PASSWORD_MAX_LEN:
            return Response({'msg': '密码长度不能大于20位'}, status=status.HTTP_400_BAD_REQUEST)
        elif password != repassword:
            return Response({'msg': '两次密码不一致'}, status=status.HTTP_400_BAD_REQUEST)
        elif not email and not mobile:
            return Response({'msg': '请输入邮箱和手机号'}, status=status.HTTP_400_BAD_REQUEST)
        elif not re.match(r'\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}', email):
            return Response({'msg': '邮箱格式不正确'}, status=status.HTTP_400_BAD_REQUEST)
        elif not re.match(r'^1[3-9]\d{9}$', mobile):
            return Response({'msg': '手机号码格式不正确'}, status=status.HTTP_400_BAD_REQUEST)
        elif User.objects.filter(username=username).exists():
            return Response({'msg': '用户名已存在'}, status=status.HTTP_400_BAD_REQUEST)
        elif email and User.objects.filter(email=email).exists():
            return Response({'msg': '邮箱已存在'}, status=status.HTTP_400_BAD_REQUEST)
        elif mobile and User.objects.filter(mobile=mobile).exists():
            return Response({'msg': '手机号已存在'}, status=status.HTTP_400_BAD_REQUEST)
        elif not avatar:
            avatar = 'default/image/avatar.png'

        data = {
            'username': username,
            'password': make_password(password),
            'is_active': request.data.get('is_active', True),
            'email': email,
            'mobile': mobile,
            'avatar': avatar
        }

        obj = User.objects.create(**data)

        if role and len(role) > 0:
            role = Role.objects.filter(id__in=request.data.get('role')).all()
            obj.role_set.set(role)

        result = {
            'message': '成功！',
            'data': {
                'id': obj.id,
                'username': username,
                'email': email,
                'mobile': mobile,
                'avatar': avatar
            }
        }
        return Response(result, status=status.HTTP_201_CREATED)

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        # 更新角色关联表
        role = Role.objects.filter(id__in=request.data.get('role')).all()
        instance.role_set.set(role)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        instance.is_delete = True
        instance.save()
        instance.role_set.set([])
        return Response(status=status.HTTP_204_NO_CONTENT)

    @action(methods=['PATCH'], detail=False, url_name='change_avatar')
    def resetPassword(self, request, pk=None):
        """
        重置密码
        :param request:
        :param pk:
        :return:
        """
        id = request.data.get('id')
        password = str(request.data.get('password'))
        repassword = str(request.data.get('repassword'))

        user = User.objects.filter(id=id, is_delete=False).first()
        if not id or not request.data.get('password') or not request.data.get('repassword'):
            return Response({'msg': '参数错误'}, status=status.HTTP_400_BAD_REQUEST)
        elif not user:
            return Response({'msg': '用户不存在'}, status=status.HTTP_400_BAD_REQUEST)
        elif not (PASSWORD_MIN_LEN <= len(password) <= PASSWORD_MAX_LEN):
            return Response({'msg': '密码长度不正确'}, status=status.HTTP_400_BAD_REQUEST)
        elif password != repassword:
            return Response({'msg': '两次密码不一致'}, status=status.HTTP_400_BAD_REQUEST)

        user.password = make_password(password)
        user.save()

        return Response({'msg': '修改成功'}, status=status.HTTP_200_OK)

    @action(methods=['PATCH'], detail=False, permission_classes=[IsAuthenticated], url_name='change_password')
    def password(self, request, pk=None):
        """
        修改密码
        """
        user = request.user
        password_old = request.data.get('password_old')

        if check_password(password_old, user.password):
            password_new = str(request.data.get('password_new'))
            password_repeat = str(request.data.get('password_repeat'))
            if not password_new or not password_repeat:
                return Response({'msg': '新密码不能为空'}, status=status.HTTP_400_BAD_REQUEST)
            elif len(password_new) < PASSWORD_MIN_LEN:
                return Response({'msg': '密码长度不能小于6位'}, status=status.HTTP_400_BAD_REQUEST)
            elif len(password_new) > PASSWORD_MAX_LEN:
                return Response({'msg': '密码长度不能大于20位'}, status=status.HTTP_400_BAD_REQUEST)
            elif password_new != password_repeat:
                return Response({'msg': '两次密码不一致'}, status=status.HTTP_400_BAD_REQUEST)
            else:
                # 两种方法皆可
                # user.password = make_password(password_new)
                user.set_password(password_new)
                user.save()
                return Response({'msg': '修改成功'}, status=status.HTTP_200_OK)

        else:
            return Response({'msg': '旧密码错误'}, status=status.HTTP_400_BAD_REQUEST)


class InfoView(APIView):
    # 去除掉全局的rbac访问权限
    permission_classes = (IsAuthenticated,)

    def get(self, request, *args, **kwargs):
        """
        获取用户信息
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        user = request.user
        if user.is_superuser:
            roles = []
            routes = []
            buttons = []
        else:
            role_list = user.role_set.filter(is_active=True).all()
            roles = []
            routes = []
            buttons = []
            permissions = []
            for role in role_list:
                roles.append(role.name)
                if len(role.permissions) > 0:
                    permissions = list(set(permissions + role.permissions.split(',')))

            if len(permissions) > 0:
                permission_list = Permission.objects.filter(id__in=permissions, is_active=True).values('id', 'codes',
                                                                                                       'type')
                for item_per in permission_list:
                    if item_per['type'] == 10:
                        routes.append(item_per['codes'])
                    elif item_per['type'] == 20:
                        buttons.append(item_per['codes'])

        result = {
            'data': {
                'id': user.id,
                'username': user.username,
                'avatar': user.avatar,
                # 'avatar': user.get_avatar(user),
                'mobile': user.mobile,
                'email': user.email,
                'is_superuser': user.is_superuser,
                # 'is_superuser': 0,
                # 'routes': ['product', 'acl', 'acl.user', 'Attr', 'role', 'permission'],
                'routes': routes,
                'roles': roles,
                # 'buttons': ['acl.user.add', 'acl.user.edit', 'acl.user.delete', 'acl.permission.add',
                #             'acl.permission.edit', 'acl.permission.delete'],
                'buttons': buttons,
                'img_domain': IMAGE_DOMAIN
            }
        }

        return Response(result, status=status.HTTP_200_OK)
